﻿using System;
using System.Collections.Generic;
using System.Linq;
using Fee.Orders;
using Fee.Orders.DesignWorkflow;
using Fee.Searchers;
using Identity;
using Microsoft.EntityFrameworkCore;

namespace Fee.Stores.Ef
{
    public class OrderStoreBase<T, TOrder> where T : FeeDbContext
        where TOrder : DelegateOrderBase
    {
        protected readonly T Context;

        public OrderStoreBase(T context)
        {
            Context = context;
        }

        public IEnumerable<TOrder> List(DelegateOrderSearch searcher, out int total)
        {
            var roleIds = searcher.Roles.Select(f => f.Id);
            var adminRole = Context.AdminRoleId();
            var hasAdmin = roleIds.Contains(adminRole);

            var query = from _ in Context.Set<TOrder>()
                        join
                            activity in Context.WorkActivities on _.Id equals activity.ProcessInstance.Id
                        where (string.IsNullOrEmpty(searcher.StationName) ||
                               _.ConstructionTask.Station.Code.Contains(searcher.StationName))
                              &&
                              (searcher.Status == null || searcher.Status == _.Status)
                              && (
                                  activity.DepositUser.Id == searcher.UserId || hasAdmin
                              )
                        select _.Id;
            total = query.Distinct().Count();
            return Context.Set<TOrder>().Include(f => f.ConstructionTask)
                .ThenInclude(f => f.Station)
                .ThenInclude(f => f.District)
                .Include(f => f.User).Skip(searcher.GetSkip()).Take(searcher.GetTake()).Where(f => query.Contains(f.Id))
                .Select(f => f);
        }

        public TOrder GetById(int id, Func<IQueryable<TOrder>, IQueryable<TOrder>> addNewInclude)
        {
            IQueryable<TOrder> result = Context.Set<TOrder>()
                    .Include(f => f.Details).ThenInclude(f => f.Contract).ThenInclude(f => f.Vendor)
                    .Include(f => f.Details).ThenInclude(f => f.Project)
                    .Include(f => f.ConstructionTask).ThenInclude(f => f.Station).ThenInclude(f => f.District)
                    .Include(f => f.ConstructionTask).ThenInclude(f => f.Station).ThenInclude(f => f.OrderDistrict)
                    .Include(f => f.ConstructionTask).ThenInclude(f => f.Details).ThenInclude(f => f.Contract)
                    .Include(f => f.ConstructionTask).ThenInclude(f => f.Details).ThenInclude(f => f.Project)
                    .Include(f => f.ConstructionTask).ThenInclude(f => f.CostDetails).ThenInclude(f => f.ProcessInfo)
                    .Include(f => f.User)
                    .Include(f => f.WorkProcess).ThenInclude(f => f.Items).ThenInclude(f => f.Role)
                ;

            result = addNewInclude(result);

            return result.FirstOrDefault(_ => _.Id == id);
        }
    }
}